import { useEffect, useState, useCallback, useRef, useImperativeHandle } from 'react';
import { withSize } from 'react-sizeme';
import { Badge, Pagination, Empty, Spin } from 'antd';
import { useErrorBoundary } from 'use-error-boundary';
import { LoadingOutlined } from '@ant-design/icons';
import { debounce, getCodeAtLength } from '@inbiz/utils';
import { useGetMessageEffect } from './hook';
import { setReaded } from '../service';
import { TextWidget } from '@inbiz/react';
import { useDebounceFunc, useTemplate } from '@inbiz/hooks'
import './style.less';

const MessageDetail = (props: any) => {
  const { selectReadState, allGroup, group, msgOpenLength, reFreshTabs, size, emit, callBackEvents, viewtype, modalType, activeGroupKey, refsd, controlId, emptyData } = props;
  const request = useGetMessageEffect();
  const [list, $list] = useState<any[]>([]);
  const [listTotal, $listTotal] = useState(0);
  const [detailFontNum, $detailFontNum] = useState(0);
  const [refresh, $refresh] = useState(false);
  const [currentPage, $currentPage] = useState(1);
  const [loading, $loading] = useState<boolean>(false);
  const [beforeItem, $beforeItem] = useState<any>(null)
  const [loadMore, $loadMore] = useState<boolean>(false)
  const loadMoreRef = useRef<boolean>(false)
  const [customEmptyImage] = useState<any>(emptyData?.image || Empty.PRESENTED_IMAGE_SIMPLE)
  const [emptyImageHeight] = useState<number>(emptyData?.imageHeight || 40)
  const [emptyDescription] = useState<string>(emptyData?.description || 'Message.tips.no_data')

  // 是否是左右弹窗视图
  const stop = useRef<boolean>()
  stop.current = viewtype == 'modal' && modalType === 'leftRight'

  // 获取详情列表
  const getList = useDebounceFunc((pageIndex?: number) => {
    $loading(true);
    request({
      pageIndex: pageIndex ? pageIndex : 1,
      pageNumber: stop.current ? 15 : props.rememberNum,
      readState: selectReadState,
      group: group,
      allGroup: (!props.activeGroupKey || props.activeGroupKey === '') ? allGroup : allGroup?.filter((i: any) => (i.groupKey === props.activeGroupKey.substring(props.activeGroupKey.indexOf('_') + 1) && i.appId === props.activeGroupKey.substring(0, props.activeGroupKey.indexOf('_')))),
      callback: (res: any) => {
        $list(res.Items);
        $listTotal(res.TotalCount);
        $loading(false);
      },
    })
  })

  useImperativeHandle(refsd, () => ({
    refreshList: () => {
      if (stop.current) {
        getList();
        $currentPage(1);
      }
    },
    beforeItem
  }), [activeGroupKey, beforeItem])

  // 列表、上下弹窗请求数据
  useEffect(() => {
    if (stop.current) return
    getList();
    $currentPage(1);
  }, [selectReadState, group, allGroup, activeGroupKey]);

  // 左右弹窗请求数据
  useEffect(() => {
    if (stop.current) {
      getList();
      $currentPage(1);
    }
  }, [activeGroupKey])

  useEffect(() => {
    //假如传递限制长度值
    if (msgOpenLength) {
      $detailFontNum(msgOpenLength);
      return;
    }
    //  未传自动计算
    let messageDetail = size;
    if (messageDetail?.width) {
      let trueDetail = messageDetail?.width - 171;
      const fontNum = trueDetail / 2;
      $detailFontNum(fontNum);
    }
  }, [refresh, msgOpenLength, size]);

  // 自适应宽度
  useEffect(() => {
    const updateSize = debounce({
      fn: () => {
        $refresh(!refresh);
      },
      delay: 100,
    });
    window.addEventListener('resize', updateSize);
    return () => window.removeEventListener('resize', updateSize);
  }, [refresh]);

  // 处理请求追加的数据
  const obser = useCallback(((entries: any) => {
    // 如果footer不可见就返回
    if (entries[0].intersectionRatio <= 0) return
    // 初始化请求中-退出
    if (loading) return
    // 上次请求还未完成
    if (loadMoreRef.current) return
    // 加载更多
    if (listTotal > 0 && currentPage * 15 < listTotal) {
      $loadMore(true)
      loadMoreRef.current = true
      request({
        pageIndex: currentPage + 1,
        pageNumber: stop.current ? 15 : props.rememberNum,
        readState: props.selectReadState,
        group: group,
        allGroup: (!activeGroupKey || activeGroupKey === '') ? allGroup : allGroup?.filter((i: any) => (i.groupKey === activeGroupKey.substring(activeGroupKey.indexOf('_') + 1) && i.appId === activeGroupKey.substring(0, activeGroupKey.indexOf('_')))),
        callback: (res: any) => {
          if (!Array.isArray(res.Items)) {
            $loadMore(false)
            loadMoreRef.current = false
            return
          }
          $list((pre: any[]) => {
            const li = [...pre, ...res.Items]
            const ids: string[] = []
            const newList: any[] = []
            li.forEach((v: any) => {
              if (!ids.includes(v.Id)) {
                ids.push(v.Id)
                newList.push(v)
              }
            })
            return newList
          });
          $listTotal(res.TotalCount);
          $currentPage(currentPage + 1)
          $loadMore(false)
          loadMoreRef.current = false
        },
      })
    }
  }), [listTotal, currentPage, activeGroupKey, loading])

  const intersectionObserver = new IntersectionObserver(obser)

  // 监听触底
  useEffect(() => {
    stop.current && intersectionObserver.observe(document.getElementById(`${props.controlId}_scroll_footer`) as Element)
    return () => {
      stop.current && intersectionObserver.disconnect()
    }
  }, [obser])

  // 设置某条消息已经读取
  const oneReaded = useCallback(
    (record: any) => {
      if (props.selectReadState == 0) {
        $loading(true);
      }
      setReaded({
        id: record.Id,
      })
        .then((res) => {
          if (res) {
            reFreshTabs && reFreshTabs();
            window.parent.postMessage({ type: 'refresh', id: props.controlId }, location.origin);
            if (props.selectReadState != 0) {
              // 未读
              $list((pre: any[]) => {
                for (let i = 0; i < pre.length; i++) {
                  if (pre[i].Id === record.Id) {
                    pre[i].MsgRead = true;
                    break;
                  }
                }
                return pre;
              });
              return;
            }
            getList(currentPage);
          }
        })
        .catch(() => {
          $loading(false);
        });
    },
    [getList, reFreshTabs, currentPage, props.selectReadState],
  );

  // 设置某条消息已经读取
  const oneReadedTimeOut = useCallback(
    (record: any) => {
      // 已读列表不做处理
      if (props.selectReadState == 1) return
      // 重复点击不做处理
      if (record.Id == beforeItem?.Id) return
      setReaded({
        id: record.Id,
      })
        .then((res) => {
          if (res) {
            $list((pre: any[]) => pre.map((v: any) => {
              let i = { ...v }
              if (i.Id === record.Id) {
                i.MsgRead = true
              }
              return i
            }));
          }
        })
        .catch(() => { });
      if (beforeItem) {
        reFreshTabs && reFreshTabs();
        window.parent.postMessage({ type: 'refresh', id: props.controlId }, location.origin);
        $list((pre: any[]) => pre.filter((i: any) => !i.MsgRead));
      }
      $beforeItem(record)
    },
    [getList, reFreshTabs, currentPage, props.selectReadState, beforeItem],
  );

  // 展开、收起
  const changeColl = (item: any) => {
    $list((preList: any[]) => {
      const newList = preList.map((msg: any) => {
        if (item.Id == msg.Id) {
          msg = {
            ...msg,
            isColl: msg.isColl ? false : true,
          };
        }
        return msg;
      });
      return newList;
    });
  };

  let ChartLength = 0;
  return (
    <Spin spinning={loading}>
      <div className="messageDetail scrollbarHover">
        {loading ? null : list?.map((item: any, idx: number) => {
          ChartLength = getCodeAtLength(item.MsgContent);
          return (
            <ItemContent
              key={item.TemplatePath && item.TemplatePath?.trim() !== '' ? item.Id ?? `key${idx}` : `${item.Id}${size.width}`}
              item={item}
              emit={emit}
              callBackEvents={callBackEvents}
              oneReaded={oneReaded}
              oneReadedTimeOut={oneReadedTimeOut}
              ChartLength={ChartLength}
              detailFontNum={detailFontNum}
              changeColl={changeColl}
              selectReadState={props.selectReadState}
              viewtype={viewtype}
              modalType={modalType}
            />
          );
        })}
        {!loading && list?.length < 1 && (
          <Empty
            style={{ marginTop: 150 }}
            image={loading ? null : customEmptyImage}
            imageStyle={{
              height: emptyImageHeight,
            }}
            description={loading ? '' : <TextWidget>{emptyDescription}</TextWidget>}
          ></Empty>
        )}
        {
          stop.current ? <div className="msg-scroll-footer" id={`${props.controlId}_scroll_footer`}>
            {loadMore ? <><LoadingOutlined /><span>加载中</span></> : null}
          </div> : null
        }
      </div>

      <div className="msg-pagination">
        {
          stop.current ?
            null :
            <Pagination
              size="small"
              simple
              defaultCurrent={1}
              current={currentPage}
              pageSize={props.rememberNum || 10}
              total={listTotal}
              showQuickJumper
              hideOnSinglePage
              onChange={(page: any) => {
                $currentPage(page);
                getList(page);
              }}
            />
        }
      </div>
    </Spin>
  );
};

export default withSize()(MessageDetail);

const ItemContent = (props: any) => {
  const { item, oneReaded, oneReadedTimeOut, ChartLength, detailFontNum, changeColl, emit, callBackEvents, viewtype, modalType } = props;
  const contentDom = useRef<any>();
  const [height, $height] = useState(0);
  const [Temp] = useTemplate(item.TemplatePath)
  const { ErrorBoundary, didCatch } = useErrorBoundary();
  useEffect(() => {
    $height(contentDom.current?.clientHeight || 0);
  }, []);
  return (
    <div className='mes-lis-ite-con'
      style={{ cursor: item.MsgRead === true ? '' : 'pointer' }}
      onClick={() => {
        if (item.MsgRead === false) {
          if (viewtype == 'modal' && modalType === 'leftRight') {
            oneReadedTimeOut(item)
          } else {
            oneReaded(item)
          }
        }
      }}
      key={item.Id}
    >
      {
        item.TemplatePath && item.TemplatePath?.trim() !== '' ?
          Temp?.default ? <>
            {
              didCatch ? <div className='inbiz-message-template-error'>模板解析失败，请检查js语法</div> :
                <ErrorBoundary>
                  {(viewtype == 'modal' && modalType === 'leftRight') || item.MsgRead !== false ? null : (
                    <Badge
                      style={{ position: 'absolute', left: 10, top: 10, height: 10, width: 10 }}
                      status="error"
                    />
                  )}
                  {/* @ts-ignore */}
                  <Temp.default parameter={JSON.parse(item.Parameter)} record={item} emit={emit} callBackEvents={callBackEvents} />
                </ErrorBoundary>
            }
          </> : null :
          <div className="msg-detail">
            <div className="msg-header">
              <div className="msg-title" title={item.MsgTitle}>
                {(viewtype == 'modal' && modalType === 'leftRight') || item.MsgRead !== false ? null : (
                  <Badge
                    style={{ position: 'absolute', left: -5, height: 10, width: 10 }}
                    status="error"
                  />
                )}
                {item.MsgTitle}
              </div>
              <div className="msg-time">{item.MsgTime}</div>
            </div>
            <div
              className={`msg-content ${item.isColl ? 'isColl' : ''}`}
              style={{ maxHeight: ChartLength === 0 ? '10000px' : undefined }}
            >
              <div
                className={`msg-content-nav ${item.isColl ? 'isColl' : ''}`}
                style={{ display: ChartLength === 0 ? 'block' : undefined }}
                dangerouslySetInnerHTML={{ __html: item.MsgContent }}
              ></div>
              <div
                ref={contentDom}
                className="msg-content-nav-hide"
                dangerouslySetInnerHTML={{ __html: item.MsgContent }}
              ></div>
            </div>
            {(ChartLength > detailFontNum || (ChartLength !== 0 && height > 60)) && (
              <div
                className="msg-open"
                onClick={(e) => {
                  e.stopPropagation();
                  e.preventDefault();
                  if (props.selectReadState != 0 && item.MsgRead === false) {
                    oneReaded(item);
                  }
                  changeColl(item);
                }}
              >
                <>
                  <TextWidget>
                    {!item.isColl ? 'Message.tips.open' : 'Message.tips.put_away'}
                  </TextWidget>
                  {/* 展开 | 收起 */}
                  <span
                    className={
                      item.isColl ? 'message-icon message-icon-open' : 'message-icon message-icon-close'
                    }
                  >
                    <svg
                      id="展开"
                      xmlns="http://www.w3.org/2000/svg"
                      width="16"
                      height="16"
                      viewBox="0 0 16 16"
                    >
                      <rect
                        id="矩形_2463"
                        data-name="矩形 2463"
                        width="16"
                        height="16"
                        fill="#bbb"
                        opacity="0"
                      />
                      <path
                        id="路径_2164"
                        data-name="路径 2164"
                        d="M26.13,2.858a.849.849,0,0,0-1.211,0L20.382,7.395,15.845,2.858a.855.855,0,1,0-1.209,1.208l4.537,4.54.909.908a.419.419,0,0,0,.6,0l.909-.909L26.13,4.068a.849.849,0,0,0,0-1.209Z"
                        transform="translate(-12.383 2.359)"
                        fill="#bbb"
                      />
                    </svg>
                  </span>
                </>
              </div>
            )}
          </div>
      }
    </div>
  );
};
